package com.calwen.xsmarthome.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.URLUtil;
import com.alibaba.fastjson2.JSON;
import com.calwen.xsmarthome.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import okio.Buffer;
import okio.BufferedSource;

import java.io.IOException;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

@Slf4j
public class OkHttpUtil {
    private static final OkHttpClient CLIENT;

    static {
        CLIENT = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES))
                .build();
    }

    private static OkHttpClient getClient() {
        return CLIENT;
    }

    public static String doGet(String url, Object data, Map<String, Object> header) {
        String query = Optional.ofNullable(data)
                .map(e -> "?" + URLUtil.buildQuery(BeanUtil.beanToMap(data), null))
                .orElse("");


        Request request = new Request.Builder()
                .url(url + query)
                .headers(buildHeaders(header))
                .get()
                .build();

        try (Response response = getClient().newCall(request).execute()) {
            return response.body() != null ? response.body().string() : null;
        } catch (IOException e) {
            log.error("[OkHttpUtil] doGet http 请求异常 message:{}", e.getMessage(), e);
            throw new ServiceException("http 请求异常");
        }
    }

    public static Response doGetResponse(String url, Object data, Map<String, Object> header) {
        String query = Optional.ofNullable(data)
                .map(e -> "?" + URLUtil.buildQuery(BeanUtil.beanToMap(data), null))
                .orElse("");


        Request request = new Request.Builder()
                .url(url + query)
                .headers(buildHeaders(header))
                .get()
                .build();

        try (Response response = getClient().newCall(request).execute()) {
            return response;
        } catch (IOException e) {
            log.error("[OkHttpUtil] doGet http 请求异常 message:{}", e.getMessage(), e);
            throw new ServiceException("http 请求异常");
        }
    }

    private static Headers buildHeaders(Map<String, Object> headerMap) {
        Headers.Builder headersBuilder = new Headers.Builder();
        if (headerMap != null) {
            headerMap.forEach((key, value) -> {
                if (key != null) {
                    headersBuilder.add(key, value.toString());
                }
            });
        }
        return headersBuilder.build();
    }

    private static FormBody buildFormBody(Object data) {
        FormBody.Builder formBuilder = new FormBody.Builder();
        Map<String, Object> dataMap = BeanUtil.beanToMap(data);
        if (dataMap != null) {
            dataMap.forEach((key, value) -> {
                if (key != null) {
                    formBuilder.add(key, value.toString());
                }
            });
        }
        return formBuilder.build();
    }

    public static String doPost(String url, Object data, Map<String, Object> header) {
        RequestBody body = RequestBody.create(JSON.toJSONString(data), MediaType.get("application/json; charset=utf-8"));
        Request request = new Request.Builder()
                .url(url)
                .headers(buildHeaders(header))
                .post(body)
                .build();

        try (Response response = getClient().newCall(request).execute()) {
            return response.body() != null ? response.body().string() : null;
        } catch (IOException e) {
            log.error("[OkHttpUtil] doPost http 请求异常 message:{}", e.getMessage(), e);
            throw new ServiceException("http 请求异常");
        }
    }

    public static String doPostFormBody(String url, Object data, Map<String, Object> header) {
        Request request = new Request.Builder()
                .url(url)
                .headers(buildHeaders(header))
                .post(buildFormBody(data))
                .build();

        try (Response response = getClient().newCall(request).execute()) {
            return response.body() != null ? response.body().string() : null;
        } catch (IOException e) {
            log.error("[OkHttpUtil] doPost http 请求异常 message:{}", e.getMessage(), e);
            throw new ServiceException("http 请求异常");
        }
    }

    public static String doPostStream(String url, Object data, Map<String, Object> header, Consumer<String> onChunk) {
        RequestBody body = RequestBody.create(JSON.toJSONString(data), MediaType.get("application/json; charset=utf-8"));
        Request request = new Request.Builder()
                .url(url)
                .headers(buildHeaders(header))
                .post(body)
                .build();

        try (Response response = getClient().newCall(request).execute()) {
            if (response.body() == null) {
                throw new ServiceException("http 请求异常: 响应 body 为空");
            }

            BufferedSource source = response.body().source();
            Buffer buffer = new Buffer();
            while (!source.exhausted()) {
                source.read(buffer, 1024 * 1024);
                String str = buffer.readUtf8();
                onChunk.accept(str);
            }
        } catch (IOException e) {
            log.error("[OkHttpUtil] doPostStream http 请求异常 message:{}", e.getMessage(), e);
            throw new ServiceException("http 请求异常");
        }
        return null;
    }

}
